<?php
	/**
	  * @package	PSQLWrapper
	  * @name		PSQLLink
	  * @brief		Clase abstracta para conectarse a un servidor PostgreSQL (Solo link al servidor)
	  * @author		Hermann D. Schimpf <hschimpf@gschimpf.com>
	  * @license	http://opensource.org/licenses/gpl-2.0.php
	  * @date		2010-03-13
	  * @version	0.1.0
  	 **/

	abstract class PSQLLink extends MyDebuger implements Conexion, MyVersions {
		/**
		  * Version de la clase
		  * @access	private
		  * @static
		  * @name	$version
		 **/
		private static $version			= 0;
		/**
		  * Subversion de la clase
		  * @access	private
		  * @static
		  * @name	$subversion
		 **/
		private static $subversion		= 1;
		/**
		  * Revision de la clase
		  * @access	private
		  * @static
		  * @name	$revision
		 **/
		private static $revision		= 0;

		/**
		  * Usuario para la conexion
		  * @access	private
		  * @name	$userPSQL
		 **/
		private $userPSQL	= False;
		/**
		  * Contrasena para la conexion
		  * @access	private
		  * @name	$passPSQL
		 **/
		private $passPSQL	= False;
		/**
		  * Host al cual se conectara (default: localhost)
		  * @access	private
		  * @name	$hostPSQL
		 **/
		private $hostPSQL	= 'localhost';
		/**
		  * Nombre de la Base de Datos
		  * @access	private
		  * @name	$ddbbPSQL
		 **/
		private $ddbbPSQL	= False;
		/**
		  * Conexion establecida con el servidor
		  * @access	private
		  * @name	$userPSQL
		 **/
		private $conexion		= False;

		/**
		  * Constructor de la clase
		  * @access	public
		  * @param	Boolean	Valor booleano para habilitar la depuracion de la clase
		  * @param	String	Nombre para la depuracion
		  * @return	void
		 **/
		public function __construct($debug = False, $name = __CLASS__) {
			/* enviamos el constructor del padre */
			parent::__construct($debug, $name);
		}

		/**
		  * Destructor de la clase
		  * @access	public
		  * @return	void
		 **/
		public function __destruct() {
			/* verificamos si existe una conexion */
			if ($this->isConnected())
				/* desconectamos de la DB */
				$this->desconectar();
			/* enviamos el destructor padre */
			parent::__destruct();
		}

		/**
		  * Metodo para obtener la version de la clase
		  * @access	public
		  * @static
		  * @return	String	Retorna la version de la clase con el formato: v{version}.{subversion}.{revision}
		 **/
		public static function getVersion() {
			/* retornamos la version actual de la clase */
			return 'v' . self::$version . '.' . self::$subversion . '.' . self::$revision;
		}

		/**
		  * Seteamos el usuario para la conexion
		  * @access	public
		  * @param	String	Nombre de usuario
		  * @return	void
		 **/
		public final function setUser($user = Null) {
			try {
				try {
					/* mostramos un mensaje */
					$this->show('Almacenando el usuario para la conexion..', False);
					/* realizamos algunas verificaciones */
					$this->verificarUser($user);
					/* almacenamos el usuario */
					$this->saveValue('userPSQL', $user);
					/* mostramos ok al mensaje */
					$this->showOK();
				} catch (Exception $e) {
					/* convertimos la excepcion a mi excepcion */
					$this->newException($e);
				}
			} catch (MyException $e) {
				/* comstramos el mensaje */
				$this->show($e->getMensaje());
			}
		}

		/**
		  * Seteamos la contrasena para la conexion
		  * @access	public
		  * @param	String	Contrasena del usuario
		  * @return	void
		 **/
		public final function setPass($pass = Null) {
			try {
				try {
					/* mostramos un mensaje */
					$this->show('Almacenando la contrasena para la conexion..', False);
					/* realizamos algunas verificaciones */
					$this->verificarPass($pass);
					/* almacenamos la contrasena */
					$this->saveValue('passPSQL', $pass);
					/* mostramos ok al mensaje */
					$this->showOK();
				} catch (Exception $e) {
					/* convertimos la excepcion a mi excepcion */
					$this->newException($e);
				}
			} catch (MyException $e) {
				/* comstramos el mensaje */
				$this->show($e->getMensaje());
			}
		}

		/**
		  * Seteamos el host para la conexion
		  * @access	public
		  * @param	String	Nombre del host
		  * @return	void
		 **/
		public final function setHost($host = Null) {
			try {
				try {
					/* mostramos un mensaje */
					$this->show('Almacenando el host para la conexion..', False);
					/* realizamos algunas verificaciones */
					$this->verificarHost($host);
					/* almacenamos el host */
					$this->saveValue('hostPSQL', $host);
					/* mostramos ok al mensaje */
					$this->showOK();
				} catch (Exception $e) {
					/* convertimos la excepcion a mi excepcion */
					$this->newException($e);
				}
			} catch (MyException $e) {
				/* comstramos el mensaje */
				$this->show($e->getMensaje());
			}
		}

		/**
		  * Seteamos la base de datos
		  * @access	public
		  * @param	String	Nombre de la Base de Datos
		  * @return	void
		 **/
		public final function setDB($db = Null) {
			try {
				try {
					/* mostramos un mensaje */
					$this->show('Almacenando la base de datos para la conexion..', False);
					/* realizamos algunas verificaciones */
					$this->verificarDB($db);
					/* almacenamos la base de datos */
					$this->saveValue('ddbbPSQL', $db);
					/* mostramos ok al mensaje */
					$this->showOK();
				} catch (Exception $e) {
					/* convertimos la excepcion a mi excepcion */
					$this->newException($e);
				}
			} catch (MyException $e) {
				/* comstramos el mensaje */
				$this->show($e->getMensaje());
			}
		}

		/**
		  * Seteamos los datos completos de la conexion
		  * @access	public
		  * @param	String	Nombre del host
		  * @param	String	Nombre de usuario
		  * @param	String	Contrasena del usuario
		  * @param	String	Nombre de la Base de Datos
		  * @return	void
		 **/
		public final function setConnectionData($host = Null, $user = Null, $pass = Null, $ddbb = Null) {
			/* almacenamos el host */
			$this->setHost($host);
			/* almacenamos el user */
			$this->setUser($user);
			/* almacenamos el pass */
			$this->setPass($pass);
			/* almacenamos la base de datos */
			$this->setDB($ddbb);
		}

		public final function conectar() {
			try {
				/* verificamos los datos para la conexion */
				$this->verificarDatosConexion();
				/* realizamos la conexion al host */
				$this->conectToHost();
				/* retornamos true */
				return True;
			} catch (MyException $e) {
				/* comstramos el mensaje */
				$this->show($e->getMensaje());
				/* retornamos false */
				return False;
			}
		}

		public final function desconectar() {
			try {
				try {
					/* mostramos un mensaje */
					$this->show('Desconectando del host ' . $this->blue($this->italic($this->getHost())) . '..', False);
					/* verificamos si hay una conexion abierta */
					$this->verificarConexion();
					/* cerramos la conexion */
					$this->cerrarConexion();
					/* mostramos ok al mensaje */
					$this->showOK();
				} catch (Exception $e) {
					/* convertimos la excepcion a mi excepcion */
					$this->newException($e);
				}
			} catch (MyException $e) {
				/* comstramos el mensaje */
				$this->show($e->getMensaje());
			}
		}

		protected function verificarConexion() {
			/* verificamos si estamos conectados al host */
			if ($this->isConnected() === False)
				/* salimos con una excepcion */
				$this->newException('No existe una conexion abierta');
			/* verificamos si la conexion caduco */
			if (pg_ping($this->getLink()) === False)
				/* salimos con una excepcion */
				$this->newException('La conexion con el host ha caducado');
		}

		private function verificarUser($user) {
			/* verificamos el valor ingresado */
			$this->verificarValor($user, Array('null' => 'No se especifico un usuario'));
			/* verificamos si existe una conexion activa */
			if ($this->isConnected() === True)
				/* salimos con una excepcion */
				$this->newException('El usuario no se puede modificar. Existe una conexion activa');
		}

		private function verificarPass($pass) {
			/* verificamos el valor ingresado */
			$this->verificarValor($pass, Array('null' => 'No se especifico una contrasena'));
			/* verificamos si existe una conexion activa */
			if ($this->isConnected() === True)
				/* salimos con una excepcion */
				$this->newException('La contrasena no se puede modificar. Existe una conexion activa');
		}

		private function verificarHost($host) {
			/* verificamos el valor ingresado */
			$this->verificarValor($host, Array('null' => 'No se especifico un nombre de host'));
			/* verificamos si existe una conexion activa */
			if ($this->isConnected() === True)
				/* salimos con una excepcion */
				$this->newException('El host no se puede modificar. Existe una conexion activa');
		}

		private function verificarDB($db) {
			/* verificamos el valor ingresado */
			$this->verificarValor($db, Array('null' => 'No se especifico una base de datos'));
			/* verificamos si existe una conexion activa */
			if ($this->isConnected() === True)
				/* salimos con una excepcion */
				$this->newException('La base de datos no se puede modificar. Existe una conexion activa');
		}

		private function verificarDatosConexion() {
			/* creamos una variable temporal */
			$error = False;
			/* mostramos un mensaje */
			$this->show('Verificando datos para la conexion..', False);
			/* verificamos el host */
			if ($this->getHost() === False)
				/* almacenamos el mensaje de error */
				$error = 'el nombre del host';
			/* verificamos la contrasena */
			if ($this->getPass() === False)
				/* almacenamos el mensaje de error */
				$error = 'la contrasena';
			/* verificamos el usuario */
			if ($this->getUser() === False)
				/* almacenamos el mensaje de error */
				$error = 'el nombre de usuario';
			/* verificamos la base de datos */
			if ($this->getDB() === False)
				/* almacenamos el mensaje de error */
				$error = 'el nombre de la base de datos';
			/* verificamos si hay algun error */
			if ($error !== False)
				/* salimos con una excepcion */
				$this->newException("No se especifico $error para la conexion");
			/* mostramos el OK al mensaje */
			$this->showOK();
		}

		private function conectToHost() {
			try {
				/* mostramos un mensaje */
				$this->show('Conectando al host ' . $this->blue($this->italic($this->getHost())) . '..', False);
				/* verificamos si ya estamos conectados */
				if ($this->isConnected() === True)
					/* salimos con una excepcion */
					$this->newException('Ya existe una conexion activa');
				/* intentamos crear la conexion */
				$this->saveValue('conexion', pg_connect('host=' . $this->getHost() . ' user=' . $this->getUser() . ' password=' . $this->getPass() . ' dbname=' . $this->getDB()));
				/* mostramos ok al mensaje */
				$this->showOK();
			} catch (Exception $e) {
				/* convertimos la excepcion a mi excepcion */
				$this->newException($e);
			}
		}

		private function cerrarConexion() {
			/* cerramos la conexion */
			pg_close($this->getLink());
			/* vaciamos el atributo conexion */
			$this->emptyConexion();
		}

		private function emptyConexion() {
			/* eliminamos el valor de la conexion */
			$this->saveValue('conexion', False);
		}

		private function getHost() {
			/* retornamos el host */
			return $this->getValue('hostPSQL');
		}

		private function getUser() {
			/* retornamos el usuario */
			return $this->getValue('userPSQL');
		}

		private function getPass() {
			/* retornamos la contrasena */
			return $this->getValue('passPSQL');
		}

		private function getDB() {
			/* retornamos la base de datos */
			return $this->getValue('ddbbPSQL');
		}

		protected function getLink() {
			/* retornamos la conexion */
			return $this->conexion;
		}

		private function isConnected() {
			/* retornamos el estado de la conexion */
			return $this->getLink();
		}

		private function verificarValor($value, $errors) {
			/* verificamos si el valor es nulo */
			if ($value === Null)
				/* salimos con una excepcion */
				$this->newException($errors['null']);
		}

		protected function saveValue($attr, $value) {
			/* verificamos si el atributo existe */
			$this->verificarAtributo($attr);
			/* almacenamos el valor en el atributo */
			$this->$attr = $value;
		}

		private function verificarAtributo($attr) {
			/* verificamos si el atributo existe */
			if (!isset($this->$attr))
				/* salimos con una exception */
				$this->newException('El atributo ' . $this->italic($attr) . ' no existe');
 		}

		protected function getValue($attr) {
			/* verificamos si el atributo existe */
			$this->verificarAtributo($attr);
			/* retornamos el valor */
			return $this->$attr;
		}
	}
?>